package Servlet;

import Service.AttachmentService;
import Service.UserService;
import entity.ArticleAttachment;
import entity.User;
import exception.BusinessException;
import utils.DBUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @Author Su
 * @Date 2025/4/30 16:38
 * @Version 1.0 （版本号）
 */
@WebServlet("/api/attachments/*")
public class AttachmentDownloadServlet extends HttpServlet {
    private static final int BUFFER_SIZE = 8192; // 8KB缓冲区
    private AttachmentService attachmentService;

    @Override
    public void init() throws ServletException {
        try {
            Connection connection = DBUtil.getConnection();
            this.attachmentService = new AttachmentService(connection);
        } catch (SQLException e) {
            throw new ServletException("初始化数据库连接失败", e);
        }
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        try {

            User user = (User) req.getSession().getAttribute("user");
            System.out.println("解析附件");
            // 1. 解析附件ID
            String pathInfo = req.getPathInfo(); // 格式: /{attachmentId}/[download|preview]
            String[] parts = pathInfo.split("/");
            int attachmentId = Integer.parseInt(parts[1]);
            String mode = parts.length > 2 ? parts[2] : "download";
            // 2. 获取附件记录（带权限检查）
            System.out.println(attachmentService);
            ArticleAttachment attachment = attachmentService.getAttachmentWithAuthCheck(
                    attachmentId,user.getUserId()
            );
            // 3. 准备文件流
            File file = new File(attachment.getFilePath());
            if (!file.exists()) {
                resp.sendError(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 4. 设置响应头
            if ("download".equals(mode)) {
                resp.setHeader("Content-Disposition",
                        "attachment; filename=\"" + encodeFileName(attachment.getFileName(), req) + "\"");
            } else { // preview模式
                resp.setHeader("Content-Disposition", "inline");
            }
            resp.setContentType(attachment.getFileType());
            resp.setContentLengthLong(file.length());

            // 5. 流式传输文件
            try (InputStream in = new BufferedInputStream(new FileInputStream(file));
                 OutputStream out = new BufferedOutputStream(resp.getOutputStream())) {

                byte[] buffer = new byte[BUFFER_SIZE];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
            }

        } catch (BusinessException e) {
            resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
        } catch (Exception e) {
            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    // 处理中文文件名编码
    private String encodeFileName(String fileName, HttpServletRequest req) {
        String userAgent = req.getHeader("User-Agent");
        try {
            if (userAgent != null && userAgent.contains("MSIE")) {
                return URLEncoder.encode(fileName, "UTF-8");
            } else {
                return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            }
        } catch (Exception e) {
            return fileName;
        }
    }
}